package com.meshnetics.gb.stack.core.layer;

import com.hse.application.ApplicationLayerException;
import com.meshnetics.gb.event.EventListener;
import com.meshnetics.gb.stack.core.InformationBase;
import com.meshnetics.gb.stack.core.Stack;
import com.meshnetics.gb.stack.core.event.EventDispatcher;
import com.meshnetics.gb.stack.core.event.StackConfirm;
import com.meshnetics.gb.stack.core.event.StackRequest;

/**
 * Base isterface for all stack layers.
 *
 * @author mmarkov
 */
public interface StackLayer {
    /**
     * Returns the name of this layer.
     *
     * @return the name of this layer
     */
    String getName();

    /**
     * Returns EventListener of this layer for handling the incoming events.
     *
     * @return EventListener of this layer
     */
    EventListener getEventListener();

    /**
     * Returns EventDispatcher of this layer for dispatching the outgoing events.
     *
     * @return EventDispatcher of this layer
     */
    EventDispatcher getEventDispatcher();

    /**
     * Returns IDGenerator of this layer for generating unique IDs for StackRequest-s.
     *
     * @return IDGenerator of this StackLayer
     */
    IDGenerator getIDGenerator();

    /**
     * Returns the InformationBase of this layer.
     *
     * @return the InformationBase of this layer.
     */
    InformationBase getInformationBase();

    /**
     * Returns the upper StackLayer this layer is connected to.
     *
     * @return the upper StackLayer this layer is connected to
     */
    StackLayer getUpperLayer();

    /**
     * Sets the upper StackLayer this layer will be connected to.
     *
     * @param layer upper StackLayer
     */
    void setUpperLayer(StackLayer layer);

    /**
     * Returns the list of lower layers for this StackLayer.
     *
     * @return array of lower layers for this StackLayer
     */
    StackLayer[] getLowerLayers();

    /**
     * Adds the given StackLayer to the list of lower layers of this StackLayer.
     *
     * @param layer StackLayer to be added to the list
     */
    void addLowerLayer(StackLayer layer);

    /**
     * Removes the given StackLayer from the list of lower layers of this StackLayer.
     *
     * @param layer StackLayer to be removed from the list
     */
    void removeLowerLayer(StackLayer layer);

    /**
     * Returns Stack which this StackLayer is a part of.
     *
     * @return Stack which this StackLayer is a part of
     */
    Stack getStack();

    /**
     * Sets Stack which this StackLayer is a part of to the given value.
     *
     * @param stack new Stack value
     */
    void setStack(Stack stack);

    /**
     * Starts this StackLayer.
     */
    void start();

    /**
     * Stops this StackLayer.
     */
    void stop();

    /**
     * Executes the given StackRequest and returns the obtained StackConfirm.
     * This method blocks till the end of execution.
     *
     * @param req StackRequest to execute
     * @return StackConfirm for the request
     */
    StackConfirm execute(StackRequest req) throws ApplicationLayerException;

    /**
     * Executes the given request and returns the resulting confirm but waits no more than the given timeout.
     *
     * @param req StackRequest to be executed
     * @param timeout maximum waiting time in milliseconds
     * @return resulting StackConfirm
     */
    StackConfirm execute(StackRequest req, long timeout) throws ApplicationLayerException;
}
